#!/usr/bin/perl

#folders
$root_folder="/home/dongjin2/SVNROOT/ethernet-switch";
$result_folder="$root_folder/rinse_test/2_to_1/exp19"; #root dir to store experimental resutls
$aggregated_result="$result_folder/3COM_simplified_queue_model_delay.csv"; #results for all experiments, used for plot

$runs=1; # number of repeated experiment (same setting)

#used to calculate gap (not used now)
$packet_size=1500; #byte

@speed;
#specify sending rate
$start_sending_rate=100;#Mb/s
$end_sending_rate=1000;
$sending_rate_gap=100;

$num_pkts = 10000;
#100Mb/s - 1000Mb/s, every 100Mb/s, slightly less than specified rate, according to real experiment
@flow1_send_rate=(-1,-1,-1,-1,-1,-1,-1,-1, 887.1e6,-1);
@flow2_send_rate=(99.081e6, 198.162e6, 295.875e6, 396.32e6, 495.404e6, 594.63e6, 691.28e6, 791.602e6, 887.624e6, 978e6);

print "@flow1_send_rate\n";
print "@flow2_send_rate\n";

for($i=0; $i<=$#flow1_send_rate; $i++)
{
	$flow1_send_interval[$i]=$packet_size*8.0/$flow1_send_rate[$i];
	$flow2_send_interval[$i]=$packet_size*8.0/$flow2_send_rate[$i];
}

print "@flow1_send_interval\n";
print "@flow2_send_interval\n";

#calculate speed and gap (gap is not used for now)
for($b=$start_sending_rate, $a=0; $b<=$end_sending_rate; $b+=$sending_rate_gap, $a++)
{
	$speed[$a]=$b;
	#print "\n speed = $speed[$a]\n";
}

open(OUT_RESULT, ">$aggregated_result") or die "$aggregated_result cannot be opened.\n";
print OUT_RESULT "switch_mode, flow1(Mb/s), flow2(Mb/s), loss_rate, time_between_loss(mean), std, loss_episode, std, loss_time, std, delay_mean, delay_std\n";

#post-process data
#for($j=0; $j<=$#speed; $j++)
for($j=8; $j<=8; $j++)
{
	for($k=0; $k<=$#speed; $k++)
	#for($k=2; $k<=2; $k++)
	{
		chdir "$result_folder/$speed[$j]M/$speed[$k]M";
		print "Processing $result_folder/$speed[$j]M/$speed[$k]M\n";

		#run simulation
		system("make run");

		#extract delay/loss and sort according arrival_timestamp
		system("cat a.out \|grep \"haha\" >flow_unsort.csv");
		system("sort flow_unsort.csv > flow.csv");

		#I/O
		$in="flow.csv";
		$out_time_between_loss="flow_time_between_loss.txt";
		$out_loss_episode="flow_loss_episode.txt";
		$out_loss_time="flow_loss_time.txt";
		$out_delay="flow_delay.txt";

		open(IN, $in) or die "$in cannot be opened.\n";
		open(OUT1, ">$out_time_between_loss") or die "$out_time_between_loss cannot be opened.\n";
		open(OUT2, ">$out_loss_episode") or die "$out_loss_episode cannot be opened.\n";
		open(OUT3, ">$out_loss_time") or die "$out_loss_time cannot be opened.\n";
		open(OUT4, ">$out_delay") or die "$out_delay cannot be opened.\n";


		#compute end time
		$line=<IN>;
		chomp($line);
		@line_block=split(', ', $line);
		$arrival_time_start=$line_block[0];
		

		if($flow1_send_interval[$j]<=$flow2_send_interval[$k])
		{
			$end_time = $num_pkts*$flow1_send_interval[$j]+$arrival_time_start;
		}
		else
		{
			$end_time = $num_pkts*$flow2_send_interval[$k]+$arrival_time_start;			
		}
		print "end time = $end_time\n";

		$prev_delay=-1;
		$prev_arrival_timestamp=-1;
		$prev_loss_timestamp=-1;
			
		$prev_arrival_timestamp=$line_block[0];
		$prev_delay=$line_block[1];
		$first_arrival_timestamp=$line_block[0];
		$first_delay=$line_block[1];

		$loss_counter=0;
		$successive_loss_counter=0;
		$total_counter=1;
		$first_max_delay_found=0;
		$first_loss_found=0;

		$delay_time_first=0;
		$delay_first=0;
		$delay_rate_first=0;

		$timestamp_after_loss=-1;
		$timestamp_before_loss=-1;
				
		while(<IN>)
		{
			my($line)=$_;
			chomp($line);
			@line_block=split(', ', $line);

			if($line_block[0]>=$end_time)
			{
				last;
			}
				
			$cur_arrival_timestamp=$line_block[0];
			$cur_delay=$line_block[1];
			#print "cur_arrival_timestamp = $cur_arrival_timestamp, cur_delay = $cur_delay\n";
			#print "prev_arrival_timestamp = $prev_arrival_timestamp, prev_delay = $prev_delay\n";
				
			if($cur_delay==0)
			{
				$loss_counter=$loss_counter+1;
				$successive_loss_counter=$successive_loss_counter+1;

				if($first_loss_found == 0)
				{
					$first_loss_found=1;
					$delay_time_first=$prev_arrival_timestamp-$first_arrival_timestamp;
					$delay_first=$prev_delay-$first_delay;
					$delay_rate_first=$delay_first/$delay_time_first;
				}

				$prev_loss_timestamp=$cur_arrival_timestamp;
			}
			if($cur_delay==0 and $prev_delay!=0)
			{
				#$timestamp_before_loss=$cur_arrival_timestamp;
				$timestamp_before_loss=$prev_arrival_timestamp;
				if($timestamp_after_loss!=-1)
				{
					$time_between_loss=$timestamp_before_loss-$timestamp_after_loss;
					if($time_between_loss!=0)
					{
						#print OUT1 "$timestamp_before_loss - $timestamp_after_loss = $time_between_loss\n";
						print OUT1 "$time_between_loss\n";
					}
					
				}
			}

			if($cur_delay!=0 and $prev_delay==0)
			{
				print OUT2 "$successive_loss_counter\n";
				$successive_loss_counter=0;

				#$timestamp_after_loss=$cur_arrival_timestamp;
				$timestamp_after_loss=$prev_arrival_timestamp;

				if($timestamp_before_loss!=-1)
				{
					$loss_time=$timestamp_after_loss-$timestamp_before_loss;
					print OUT3 "$loss_time\n";
					#print OUT3 "$timestamp_after_loss - $timestamp_before_loss = $loss_time\n";
				}
			}

			if($cur_delay!=0)
			{
				print OUT4 "$cur_delay\n";
			}


			#if($cur_delay<$prev_delay and $first_max_delay_found==0)
			#{
			#	$delay_time_first=$cur_arrival_timestamp-$first_arrival_timestamp;
			#	$delay_first=$cur_delay-$first_delay;
			#	$delay_rate_first=$delay_first/$delay_time_first;
			#	$first_max_delay_found=1;
			#}

			$prev_delay = $cur_delay;
			$prev_arrival_timestamp = $cur_arrival_timestamp;
			$total_counter=$total_counter+1;
		}

		close(IN);
		close(OUT1);
		close(OUT2);
		close(OUT3);
		close(OUT4);
	
		#calculate mean and std for time_between_loss
		if($loss_counter>0)
		{
			@array_time_between_loss=compute_avg_std($out_time_between_loss);
			@array_loss_time=compute_avg_std($out_loss_time);
			@array_loss_episode=compute_avg_std($out_loss_episode);
		}
		else
		{
			@array_time_between_loss=(0,0);
			@array_loss_episode=(0,0);
			@array_loss_time=(0,0);
		}

		@array_delay=compute_avg_std($out_delay);

		#format output
		$array_time_between_loss[0]=$array_time_between_loss[0]*(10**6);
		$array_time_between_loss[1]=$array_time_between_loss[1]*(10**6);
		$array_loss_time[0]=$array_loss_time[0]*(10**6);
		$array_loss_time[1]=$array_loss_time[1]*(10**6);
		$array_delay[0]=$array_delay[0]*(10**6);
		$array_delay[1]=$array_delay[1]*(10**6);
		$array_loss_episode[0]=$array_loss_episode[0];
		$array_loss_episode[1]=$array_loss_episode[1];
		$delay_time_first=$delay_time_first*(10**6);
		$delay_rate_first=$delay_rate_first/(10**6);	

		$formatted_delay_time_first=sprintf("%.3f", $delay_time_first);
		$formatted_delay_rate_first=sprintf("%.3f", $delay_rate_first);
		$formatted_delay_first=sprintf("%.3f", $delay_first);
		$formatted_array_time_between_loss[0]=sprintf("%.3f", $array_time_between_loss[0]);
		$formatted_array_time_between_loss[1]=sprintf("%.3f", $array_time_between_loss[1]);
		$formatted_array_loss_episode[0]=sprintf("%.3f", $array_loss_episode[0]);
		$formatted_array_loss_episode[1]=sprintf("%.3f", $array_loss_episode[1]);
		$formatted_array_loss_time[0]=sprintf("%.3f", $array_loss_time[0]);
		$formatted_array_loss_time[1]=sprintf("%.3f", $array_loss_time[1]);
		$formatted_array_delay[0]=sprintf("%.3f", $array_delay[0]);
		$formatted_array_delay[1]=sprintf("%.3f", $array_delay[1]);

		$loss_rate=$loss_counter*1.0/$total_counter;

		#total output
		#"switch_mode, flow1(Mb/s), flow2(Mb/s), loss_rate, time_between_loss(mean), std, loss_episode, std, loss_time, std";
		print OUT_RESULT "NG_analytical, $speed[$j], $speed[$k], $loss_rate, $formatted_array_time_between_loss[0], $formatted_array_time_between_loss[1], $formatted_array_loss_episode[0], $formatted_array_loss_episode[1], $formatted_array_loss_time[0], $formatted_array_loss_time[1], $formatted_array_delay[0], $formatted_array_delay[1]\n";

	}
}

close(OUT_RESULT);

chdir "$root_folder/script/rinse_test";

sub compute_avg_std
{
	$in =$_[0];
	open(INPUT, $in) or die "$in cannot be opened.\n";

	@my_array;#mean,std

	$counter = 0;
	$sum = 0;
	$square_sum = 0;
	$mean = 0;
	$var = 0;
	$std = 0;
	
	while($line = <INPUT>)
	{			
		chomp($line);
		if($line!="")
		{
			$counter++;
			$sum += $line;
			$square_sum += $line**2;
        		$prev_line = $line;
		}
	}

	$mean = $sum /$counter;
	$autocor = $square_sum/$counter;
	$var = $autocor-$mean**2;
	if($var<0)
	{
		$std=0;
	}
	else
	{
		$std = sqrt($var);
	}

	#$formatted_mean=sprintf("%.3f", $mean);
	#$formatted_std=sprintf("%.3f", $std);
	close(INPUT);

	$my_array[0]=$mean;
	$my_array[1]=$std;
	return @my_array;
}
